package es.uned.etsii.si3.taller.servlets;

import java.sql.SQLException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Map;

import org.apache.struts2.interceptor.SessionAware;

import com.j256.ormlite.stmt.QueryBuilder;
import com.j256.ormlite.stmt.Where;
import com.opensymphony.xwork2.ActionSupport;

import es.uned.etsii.si3.taller.Cliente;
import es.uned.etsii.si3.taller.EmpleadoTaller;
import es.uned.etsii.si3.taller.FactoriaDAO;
import es.uned.etsii.si3.taller.FactoriaFunciones;
import es.uned.etsii.si3.taller.ParteTrabajo;
import es.uned.etsii.si3.taller.Taller;
import es.uned.etsii.si3.taller.Usuario;
import es.uned.etsii.si3.taller.Vehiculo;
import es.uned.etsii.si3.taller.VehiculoUsuario;
import es.uned.etsii.si3.taller.misc.ProporcionaFuncionalidad;

/**
 * Esta clase se encarga de la gestión de las clases de entrada 
 *
 */
public class PTPartesEntrada extends ActionSupport implements SessionAware { 

	private static final long serialVersionUID = 1L;
	
	private 	Map<String, Object>		userSession;

	private 	String 			dni;
	private 	String 			nombre;
	private 	String 			apellidos;
	private 	String 			poblacion;
	private 	String 			direccion;
	private 	int 			codigoPostal;	
	private 	String 			telefono;		
	private 	String 			descripcion;
	private		String 			fechaEntradaString;
	
	/**
	 * Métodos get y set para los parámetros que se conectan con los JSP
	 * 
	 */
	public 		String    		getNombre()       						{ return this.nombre; }
	public 		String    		getApellidos()    						{ return this.apellidos; }
	public 		String    		getDni()          						{ return this.dni; }
	public 		String    		getPoblacion()    						{ return this.poblacion; }
	public 		String    		getDireccion()    						{ return this.direccion; }
	public 		int       		getCodigoPostal() 						{ return this.codigoPostal; }
	public 		String    		getTelefono()     						{ return this.telefono; }	
	public 		String    		getDescripcion()   						{ return this.descripcion; }
	public 		String    		getFechaEntradaString()  				{ return this.fechaEntradaString; }

	public 		void 			setNombre(String s) 					{ this.nombre = s; }
	public 		void 			setApellidos(String s) 					{ this.apellidos = s; }
	public 		void 			setDni(String s) 						{ this.dni = s; }
	public 		void 			setPoblacion(String s) 					{ this.poblacion = s; }
	public 		void 			setDireccion(String s) 					{ this.direccion = s; }
	public 		void 			setCodigoPostal(int i) 					{ this.codigoPostal = i; }
	public 		void 			setTelefono(String s) 					{ this.telefono = s; }	
	public 		void    		setDescripcion(String s)				{ this.descripcion = s; }
	public 		void    		setFechaEntradaString(String s)			{ this.fechaEntradaString = s; }
	
	private 	ParteTrabajo	parteSeleccionado = null;
	public 		ParteTrabajo	getParteSeleccionado() 					{ return this.parteSeleccionado; }
	public 		void			setParteSeleccionado(ParteTrabajo pT) 	{ this.parteSeleccionado = pT; }

	private 	static int 		parteSeleccionadoID = -1;
	public 		int				getParteSeleccionadoID() 				{ return PTPartesEntrada.parteSeleccionadoID; }
	public 		void			setParteSeleccionadoID(int i) 			{ PTPartesEntrada.parteSeleccionadoID = i; }

	public 		Cliente 	 	getClienteSeleccionado() 				
								{ return PTBuscarCliente.getClienteSeleccionado(); }
	public 		void      		setClienteSeleccionado(Cliente c) 		
								{ PTBuscarCliente.setClienteSeleccionado(c); }

	public 		int  			getClienteSeleccionadoID() 				
								{ return PTBuscarCliente.getClienteSeleccionadoID(); }
	public 		void		 	setClienteSeleccionadoID(int i) 		
								{ PTBuscarCliente.setClienteSeleccionadoID(i); }
	
	private 	Taller  		tallerSeleccionado;
	public 		Taller 	 		getTallerSeleccionado() 				{ return this.tallerSeleccionado; }
	public 		void      		setTallerSeleccionado(Taller t)			{ this.tallerSeleccionado = t; }

	private 	Vehiculo  		vehiculoSeleccionado;
	public 		Vehiculo 	 	getVehiculoSeleccionado() 				{ return this.vehiculoSeleccionado; }
	public 		void      		setVehiculoSeleccionado(Vehiculo v)		{ this.vehiculoSeleccionado = v; }

	private 	static int		vehiculoSeleccionadoID = -1;
	public 		int 			getVehiculoSeleccionadoID() 			{ return PTPartesEntrada.vehiculoSeleccionadoID; }
	public 		void			setVehiculoSeleccionadoID(int i) 		{ PTPartesEntrada.vehiculoSeleccionadoID = i; }

	private 	List<Vehiculo>	listaVehiculos = null;
	public 		List<Vehiculo> 	getListaVehiculos() 					{ return this.listaVehiculos; }
	public 		void 			setListaVehiculos(List<Vehiculo> l) 	{ this.listaVehiculos = l; }

	private 	List<ParteTrabajo>	listaPartes;		
	public		List<ParteTrabajo>	getListaPartes() 						{ return this.listaPartes; }
	public 		void				setListaPartes(List<ParteTrabajo> l)	{ this.listaPartes = l; }


	/**
	 * Nos lleva a la página de crear partes de entrada
	 *  
	 * @return 	código de result para STRUTS
	 * @throws SQLException
	 */
	@ProporcionaFuncionalidad(identificador = FactoriaFunciones.JEFE_TALLER_NUEVO_PARTE_ENTRADA)	
	public String nuevoParteEntrada() throws SQLException {
		this.recuperarBusquedas();
		return SUCCESS;
	}
	
	/**
	 * Controla la creación de un parte de entrada por parte del jefe de taller
	 * <p>
	 * Comprueba que están rellenos el cliente, el vehículo, la descripción
	 * y la fecha, y que ésta tiene formato de fecha
	 * <p>
	 * En caso de estar correcto, crea el registro en la BD, dejandolo 
	 * pendiente de presupuestar
	 * 
	 * @return	código de result para STRUTS 
	 * @throws SQLException
	 */
	@ProporcionaFuncionalidad(identificador = FactoriaFunciones.JEFE_TALLER_NUEVO_PARTE_ENTRADA)	
	public String crearParteEntrada() throws SQLException {
		String res = SUCCESS;
		if ( this.getClienteSeleccionadoID() <0 ) {
			addActionError("El cliente es obligatorio");
			res = ERROR;			
		} else if ( this.getVehiculoSeleccionadoID() <0 ) {
			addActionError("El vehiculo es obligatorio");
			res = ERROR;			
		} else if ( this.getDescripcion().isEmpty() ) {
			addActionError("La descripcion es obligatoria");
			res = ERROR;			
		} else if ( this.getFechaEntradaString().isEmpty() ) {
			addActionError("La fecha de relización del parte es obligatoria");
			res = ERROR;			
		} else {
			this.recuperarBusquedas();
			Taller taller = this.getTallerSesionEmpleado();		
			Usuario usuario  = this.getClienteSeleccionado().getUsuario();
			Vehiculo vehiculo = this.getVehiculoSeleccionado();
			String descripcion = this.getDescripcion();
			//Date fechaEntrada = this.getFechaEntrada();
			SimpleDateFormat df = new SimpleDateFormat("dd/MM/yy");
			Date fechaEntrada = null;
			try {
				fechaEntrada = df.parse(this.getFechaEntradaString());
			} catch (ParseException e) {
				addActionError("Formato de la fecha erróneo");
				res = ERROR;
			}		
			ParteTrabajo pT = ParteTrabajo.crear(usuario, taller, vehiculo, descripcion, fechaEntrada);
			this.setParteSeleccionado(pT);
			this.cargarDatosCliente(this.getClienteSeleccionado());					
			pTLimpiarPE();
		}
		return res;
	}

	
	/**
	 * Limpia el formulario de creación de partes de entrada
	 */
	private void pTLimpiarPE() {
		this.setClienteSeleccionado(null);		
		this.setClienteSeleccionadoID(-1);
		this.setVehiculoSeleccionado(null);
		this.setVehiculoSeleccionadoID(-1);
		this.setDescripcion(null);
		this.setFechaEntradaString(null);		
	}

	/**
	 * Carga los datos del cliente seleccionado por el jefe de taller
	 * @param c	cliente
	 */
	private void cargarDatosCliente(Cliente c) {		
		this.setDni(c.getDni());
		this.setNombre(c.getNombre());
		this.setApellidos(c.getApellidos());
		this.setPoblacion(c.getPoblacion());
		this.setDireccion(c.getDireccion());
		this.setCodigoPostal(c.getCodigoPostal());
		this.setTelefono(c.getTelefono());
	}


	/**
	 * Carga la lista de partes confirmados por el cliente para este taller
	 * 
	 * 
	 * @return código de result para STRUTS
	 * @throws SQLException
	 * @throws ParseException
	 */
	@ProporcionaFuncionalidad(identificador = FactoriaFunciones.JEFE_TALLER_ALBARAN_DE_CUSTODIA)	
	public String cargarPartesConfirmados() throws SQLException, ParseException {
		String res = SUCCESS;
		QueryBuilder<ParteTrabajo, Integer> parteQb = FactoriaDAO.getDao(ParteTrabajo.class).queryBuilder();
		Where<ParteTrabajo, Integer> wParteQb = parteQb.where();
		wParteQb.eq(ParteTrabajo.ID_TALLER_FIELD_NAME, this.getTallerSesionEmpleado());
		wParteQb.and().eq(ParteTrabajo.ACEPTADO_FIELD_NAME, true);
		wParteQb.and().isNull(ParteTrabajo.ALBARAN_FIELD_NAME);
		this.listaPartes = parteQb.query();
		return res;
	}

	/**
	 * Permite crear un albarán de custodia, es decir, que el coche se 
	 * encuentra ya en el taller.
	 * <p>
	 * Comprueba que la fecha sea correcta, y posterior a la de creación
	 * del parte
	 * 
	 * @return código de result para STRUTS
	 * @throws SQLException
	 * @throws ParseException
	 */
	@ProporcionaFuncionalidad(identificador = FactoriaFunciones.JEFE_TALLER_ALBARAN_DE_CUSTODIA)	
	public String crearAlbaranCustodia()  throws SQLException, ParseException {
		String res = SUCCESS;
		if ( this.getFechaEntradaString().isEmpty() ) {
			addActionError("La fecha de entrada del vehiculo es obligatoria");
			res=cargarPartesConfirmados();
			res = ERROR;			
		} else {
			this.setParteSeleccionadoID(this.getParteSeleccionadoID());
			this.setParteSeleccionado(FactoriaDAO.recuperar(ParteTrabajo.class, this.getParteSeleccionadoID()));
			this.setTallerSeleccionado(this.getTallerSesionEmpleado());
			this.setFechaEntradaString(this.getFechaEntradaString());
			SimpleDateFormat df = new SimpleDateFormat("dd/MM/yy");
			Date fechaEntrada = null;
			try {
				fechaEntrada = df.parse(this.getFechaEntradaString());
				if ((getParteSeleccionado().getFechaEntrada()).after(fechaEntrada)) {
					addActionError("La fecha de entrada no puede ser anterior a la fecha de creación del parte");
					res=cargarPartesConfirmados();
					res = ERROR;
				}
				this.getParteSeleccionado().setFechaEntrada(fechaEntrada);
			} catch (ParseException e) {
				addActionError("Formato de la fecha erróneo");
				res=cargarPartesConfirmados();
				res = ERROR;
			}		
			if ( res == SUCCESS ) {
				this.setClienteSeleccionado(this.getParteSeleccionado().getUsuario().getCliente());
				this.setVehiculoSeleccionado(this.getParteSeleccionado().getVehiculo());
				this.getParteSeleccionado().setAlbaran("EnTaller");				
				this.getParteSeleccionado().update();
			}
		}
		return res;
	}

	
	/**
	 * Permite mostrar los vehículos del cliente seleccionado. 
	 * Si no se ha seleccionado ninguno da error
	 * 
	 * @return código de result para STRUTS
	 * @throws SQLException
	 */
	@ProporcionaFuncionalidad(identificador = FactoriaFunciones.JEFE_TALLER_NUEVO_PARTE_ENTRADA)	
	public String pTBuscarVehiculo() throws SQLException {
		String res = SUCCESS;
		if ( this.getClienteSeleccionadoID() <0 ) {
			addActionError("Primero tiene que seleccionar el cliente");
			res = ERROR;
		} else {
			this.cargarTablaVehiculos();
		}
		return res;
	}
	
	/**
	 * Carga la tabla de vehículos que pertenece a un cliente determinado
	 * 
	 * @throws SQLException
	 */
	private void cargarTablaVehiculos() throws SQLException {
		this.recuperarBusquedas();
		try {
			QueryBuilder<VehiculoUsuario, Integer> vUQb;
			vUQb = FactoriaDAO.getDao(VehiculoUsuario.class).queryBuilder();
			Where<VehiculoUsuario, Integer> wVUQb = vUQb.where();			
			wVUQb.eq(VehiculoUsuario.ID_USUARIO_FIELD_NAME, this.getClienteSeleccionado().getUsuario().getId());

			QueryBuilder<Vehiculo, Integer> vehiculosQb;
			vehiculosQb = FactoriaDAO.getDao(Vehiculo.class).queryBuilder();

			List<Vehiculo> lista = vehiculosQb.join(vUQb).query();
			this.setListaVehiculos(lista);
			
		} catch (SQLException e) {
			addActionError("Error al localizar los vehiculos del usuario: " + e);
		}
	}
	
	/**
	 * Cuando se ha seleccionado el vehículo, recarga los datos de la pantalla
	 * anterior
	 * 
	 * @return código de result para STRUTS
	 * @throws SQLException
	 */
	@ProporcionaFuncionalidad(identificador = FactoriaFunciones.JEFE_TALLER_NUEVO_PARTE_ENTRADA)	
	public String pTPostBuscarVehiculo() throws SQLException {
		this.recuperarBusquedas();
		return SUCCESS;
	}	

	/**
	 * Recupera los datos del cliente y el vehículo a partir de sus id
	 * 
	 * @throws SQLException
	 */
	private void recuperarBusquedas() throws SQLException {
		this.setClienteSeleccionado(FactoriaDAO.recuperar(Cliente.class, this.getClienteSeleccionadoID()));
		this.setVehiculoSeleccionado(FactoriaDAO.recuperar(Vehiculo.class, this.getVehiculoSeleccionadoID()));
	}

	/**
	 * Obtiene el taller a partir del código del jefe de taller
	 * 
	 * @return Taller	el taller en el que estamos logados
	 */
	private Taller getTallerSesionEmpleado() {
		Taller res = null;
		Usuario uS = (Usuario) userSession.get("usuario");
		QueryBuilder<EmpleadoTaller, Integer> eTQb;
		try {
			eTQb = FactoriaDAO.getDao(EmpleadoTaller.class).queryBuilder();
			Where<EmpleadoTaller, Integer> wETQb = eTQb.where();			
			wETQb.eq(EmpleadoTaller.ID_USUARIO_FIELD_NAME, uS.getId());			
			List<EmpleadoTaller> lista = wETQb.query();
			res = lista.get(0).getTaller();
		} catch (SQLException e) {
			addActionError("Error al buscar taller: " + e);
		}			
		return res;
	}
	
	public String execute() { return SUCCESS; }

	/**
	 * Permite dar valor a la sesión
	 */
	@Override
	public void setSession(Map<String, Object> session) {
		userSession = session;		
	}

}
